Maximal rectangle [Mono Stack, DP]

Time: O(MxN); Space: O(N); hard

Given a 2D binary matrix filled with 0’s and 1’s,

find the largest rectangle containing all ones and return its area.

Example 1:

Input: matrix =

[
  ["1","0","1","0","0"],
  ["1","0","1","1","1"],
  ["1","1","1","1","1"],
  ["1","0","0","1","0"]
]

Output: 6

1. Ascending stack solution

[8]:
class Solution1(object):
    def maximalRectangle(self, matrix):
        """
        :type matrix: List[List[str]]
        :rtype: int
        Ascending stack solution
        """
        def largestRectangleArea(heights):
            increasing, area, i = [], 0, 0
            while i <= len(heights):
                if not increasing or (i < len(heights) and heights[i] > heights[increasing[-1]]):
                    increasing.append(i)
                    i += 1
                else:
                    last = increasing.pop()
                    if not increasing:
                        area = max(area, heights[last] * i)
                    else:
                        area = max(area, heights[last] * (i - increasing[-1] - 1 ))
            return area

        if not matrix:
            return 0

        result = 0
        heights = [0] * len(matrix[0])
        for i in range(len(matrix)):
            for j in range(len(matrix[0])):
                heights[j] = heights[j] + 1 if matrix[i][j] == '1' else 0
            result = max(result, largestRectangleArea(heights))

        return result
[14]:
s = Solution1()
matrix = [
    ["1","0","1","0","0"],
    ["1","0","1","1","1"],
    ["1","1","1","1","1"],
    ["1","0","0","1","0"]
]
assert s.maximalRectangle(matrix) == 6
matrix = ["01101",
          "11010",
          "01110",
          "11110",
          "11111",
          "00000"]
assert s.maximalRectangle(matrix) == 9

2. DP solution

[15]:
class Solution2(object):
    """
    DP solution:
    dp[i][j] = max length of all 1 sequence ends with col j, at the i-th row
    transition:
       dp[i][j] = 0 if matrix[i][j] == '0'
                = dp[i][j-1] + 1 if matrix[i][j] == '1'
    """
    def maximalRectangle(self, matrix):
        """
        :type matrix: List[List[str]]
        :rtype: int
        """
        if not matrix:
            return 0

        result = 0
        m = len(matrix)
        n = len(matrix[0])
        L = [0 for _ in range(n)]
        H = [0 for _ in range(n)]
        R = [n for _ in range(n)]

        for i in range(m):
            left = 0
            for j in range(n):
                if matrix[i][j] == '1':
                    L[j] = max(L[j], left)
                    H[j] += 1
                else:
                    L[j] = 0
                    H[j] = 0
                    R[j] = n
                    left = j + 1

            right = n
            for j in reversed(range(n)):
                if matrix[i][j] == '1':
                    R[j] = min(R[j], right)
                    result = max(result, H[j] * (R[j] - L[j]))
                else:
                    right = j

        return result
[16]:
s = Solution2()
matrix = [
    ["1","0","1","0","0"],
    ["1","0","1","1","1"],
    ["1","1","1","1","1"],
    ["1","0","0","1","0"]
]
assert s.maximalRectangle(matrix) == 6
matrix = ["01101",
          "11010",
          "01110",
          "11110",
          "11111",
          "00000"]
assert s.maximalRectangle(matrix) == 9